package com.hhf.spring;

import com.hhf.spring.bean.Cat;
import com.hhf.spring.bean.Person;
import com.hhf.spring.config.MainConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * 注解版的spring用法
 *
 *
 * spring的大致整体工作流程：
 * 		1.spring暴露给程序员的就是要么写一个xml文件，要么就是写一堆注解，
 * 		2.不管这些xml文件也好还是注解也罢，最终都会生成一个组件或者功能配置的清单
 * 		3.这个组件或者功能配置的清单，spring就要读取，然后就决定了spring框架的各种行为
 * 		4.也就是说所有的资源被spring都用Resources来表示。
 * 		5.这些资源（xml/注解），spring底层有一个类叫ResourcesLoader（资源加载器），ResourcesLoader（资源加载器）就负责加载这些资源
 * 		6.这些资源（xml/注解）写了一些组件或者功能配置，那么实际上在spring的底层，所有的组件所有的配置都应该放在了BeanDefinition里面
 * 		7.也就是说这些资源（xml/注解），在底层spring要解析这些资源（xml/注解），然后最终生成BeanDefinition（bean的定义信息）
 * 		8.BeanDefinition（bean的定义信息）怎么来的？
 * 				8.1是由一个叫BeanDefinitionReader（bean定义信息的读取）
 * 				8.2 ResourcesLoader资源加载器	帮我们把这些资源加载来以后交给BeanDefinitionReader（bean定义信息的读取器）
 * 		        8.3 BeanDefinitionReader（bean定义信息的读取器）就把这些信息给读取来，然后放入spring里面
 * 		9.放到spring的哪里呢？
 * 				9.1 spring底层所有的组件，都得有这个Bean定义信息，所以就放在了BeanDefinitionRegistry档案馆里面
 * 		10 所以在资源（xml/注解）写的配置，会被先来加载到BeanDefinitionRegistry档案馆里面，而这个BeanDefinitionRegistry档案馆就是一个map
 * 			10.1这个map就保存每一个组件是怎么定义的
 * 			10.2 相当于这个BeanDefinitionRegistry通过解析xml，把xml里面的内容解析成一个一个类，这个类就叫BeanDefinition（bean的定义信息）
 * 		11.BeanDefinition（bean的定义信息）有了以后（也就是说只要spring一启动，它就把所有的资源一加载，把一大堆的xml/注解都转换为BeanDefinition（bean的定义信息）以后）
 *		12.接下来就是把这些BeanDefinition（bean的定义信息）挨个给他创建成对象
 *			12.1如何创建对象？
 *				12.2把所有定义的bean的信息，把它拿来经过漫长的过程就来进行对象的创建（按照bean定义信息创建对象）
 *				12.3只要这些对象创建完，那么就能在容器中可以获取了
 *		13.但问题是有些时候，在容器中拿的是单实例的，那每次获取都是获取的同一个对象，那处理这些单实例就很简单
 *		14 在整个对象创建过程中，是有各种池的：临时对象池(earlySingletonObjects)，单例工厂池(singletonFactories)，
 *									已注册的单例池(registeredSingletons)，单例对象池(singletonObjects)
 *		15 其中就有一个叫单例对象池(singletonObjects)，所有创建好的单实例对象全放在这里
 *		16 以后从工厂中获取，其实就是从这个单例对象池(singletonObjects)里面进行获取的
 *								这是整个spring的工作流程大致也就是以上这个样子
 *
 *
 *	spring是如何定义Resource的？
 *		1.是抽象IOC容器拥有了资源加载器接口 这里也就是策略模式的环境类 也就是ioc容器拿到资源解析器，
 *		  资源解析器只要传的不一样，ioc容器就可以从不一样的地方获取东西
 *		2.是在对象创建的时候就拿到了资源解析，是用getResourcePatternResolver这个方法拿到的
 *
 *
 *
 *
 */
public class AnnotationMainTest {

	public static void main(String[] args) {
		ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);


		//		Person bean = applicationContext.getBean(Person.class);
//		System.out.println(bean);
		//获取容器中的所有组件,获取所有定义信息的名字
//		String[] names = applicationContext.getBeanDefinitionNames();
//		for (String name : names) {
//			System.out.println(name);
//		}

//		Cat bean1 = applicationContext.getBean(Cat.class);
//		Cat bean2 = applicationContext.getBean(Cat.class);
//		System.out.println(bean1 == bean2);  //false

//		Person bean1 = applicationContext.getBean(Person.class);
//		Cat cat1 = bean1.getCat();
//
//		Person bean2 = applicationContext.getBean(Person.class);
//		Cat cat2 = bean2.getCat();
		//因为Person是单实例的，导致Person引用的原型组件cat，它永远也就只有这一个，
		// 都是容器中启动时创建Person对象的时候，容器初始化的cat,所以得到的cat永远都是只有一个
		//那这样就不符合原型模式的引用了

	//	System.out.println(cat1 == cat2);  //true

//		Person bean = applicationContext.getBean(Person.class);
//		ApplicationContext context = bean.getContext();
//		System.out.println(context == applicationContext);



	}

}
